﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;  
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using TileEngine.tiles;
using TileEngine.inventory;
using TileEngine.items;
using System.IO;

namespace TileEngine
{
    class Player
    {
        public World parentWorld;
        public Inventory inventory;
        public Point SpawnTile;
        public Status status;
        public Vector2 Location;//center
        public Vector2 Speed;//bir milisaniyedeki kare sayısı
        public Vector2 acc;//bir milisaniyedeki hız değişimi

        #region stats
        public int stat=0;
        public double health=80;
        public double healthMax = 100;
        public double mana=80;
        public double manaMax = 100;
        public double xp = 0;
        public double totalXp = 0;
        public double nextXP = 10;
        public double level = 1;
        public string name = "Player";


        public double healthRegen = 1;
        public double manaRegen = 1;
        public float movementSpeed=1;
        public double attackSpeed=1;
        public double strenght=5;
        public double intelligence=5;
        public double agility = 5;
        public double meleeDamage = 1;
        public double rangeDamage = 1;
        public double magicDamege = 1;
        public double meleeArmor = 0;
        public double rangeArmor = 0;
        public double magicArmor = 0;
        public double avasion = 0.1;
        public float jumpPower = 1;
        #endregion

        #region achievements
        //int achNumberofTilesDigged;
        //int achNumberofItemsPicked;
        //int achNumberofItemsCrafted;
        //int achNumberofItemsUsed;
        //int achNumbetofMinutesPassed;
        //int achMaxHeightbeen;
        //int achMinHeightbeen;
        //int achNumberofOresPicked;

        #endregion

        bool jumpKeyReleased = false;
        Vector2 jumpAcc = new Vector2(0,0);
        bool isJump=false;
        bool isDuck=false;
        bool isFiring=false;
        bool isLieDown=false;
        bool isStandingup=false;
        public bool isLookRight = true;
        int DuckTime=0;

        public int getManaMax()
        {
            return 100;
        }
        public int getHealthMax()
        {
            return 100;
        }
        public Player(World parent)
        {
            parentWorld = parent;
            Location = new Vector2(2000,1000);
            Speed = new Vector2(0,0);
            acc = new Vector2();
            inventory = new Inventory(this);
            status = new Status(this);
        }
        public void update(GameTime gameTime, KeyboardState ks)
        {
            
            if (Mouse.GetState().LeftButton == ButtonState.Pressed)
            {
                if(!isDuck && !isStandingup && !isLieDown)
                    if (!inventory.isShown)
                    {
                                if (inventory.holders[inventory.selected].items.Count != 0)
                                {
                                    inventory.holders[inventory.selected].items[0].mouseLeftClick(gameTime);
                                    isFiring = true;
                                }
                    }
            }
            if (Mouse.GetState().LeftButton == ButtonState.Released)
                isFiring = false;

            if (ks.IsKeyDown(Keys.Q))
            {
                addXp(5);
            }

            acc.X = 0;
            acc.Y = 0;
            acc += parentWorld.Gravity;
            acc -= Speed * new Vector2(0.004f,0.001f);//sürtünme
            //liquid density
            #region inactive
            if (ks.IsKeyDown(Keys.X))
            {
                isLieDown = true;
            }
            if (isLieDown && ks.IsKeyDown(Keys.Space))
            {
                isLieDown = false;
                isStandingup = true;
                DuckTime = 0;
            }
            #endregion
            if ((ks.IsKeyDown(Keys.A) || ks.IsKeyDown(Keys.Left)) && !isDuck && !isLieDown && !isStandingup)
            {
                acc += new Vector2((-0.000005f*gameTime.ElapsedGameTime.Milliseconds), 0);
                isLookRight = false;
            }
            if ((ks.IsKeyDown(Keys.D) || ks.IsKeyDown(Keys.Right)) && !isDuck && !isLieDown && !isStandingup)
            {
                isLookRight = true;
                acc += new Vector2((0.000005f * gameTime.ElapsedGameTime.Milliseconds), 0);
            }

            if ((ks.IsKeyDown(Keys.Space)) && !isDuck && !isLieDown && !isStandingup)
            {
                if (!isJump)
                {
                    isJump = true;
                    jumpAcc.Y = -0.00055f;
                    
                }
                else if (jumpKeyReleased == false)
                {
                    jumpAcc.Y = jumpAcc.Y + 0.00004f;
                    if (jumpAcc.Y >= 0)
                        jumpKeyReleased = true;
                    
                }
            }
            if (isJump && (ks.IsKeyUp(Keys.Space)))
            {
                jumpAcc.Y = 0;
                jumpKeyReleased = true;
            }
            acc += jumpAcc;
            Speed.X += acc.X*gameTime.ElapsedGameTime.Milliseconds;
            Speed.Y += acc.Y*gameTime.ElapsedGameTime.Milliseconds;
            if (isCollide(new Vector2(Location.X + Speed.X * gameTime.ElapsedGameTime.Milliseconds * Global.tileSize.X*movementSpeed, Location.Y)))
            {
                Speed.X = 0;
            }
            if (isCollide(new Vector2(Location.X, Location.Y + Speed.Y * gameTime.ElapsedGameTime.Milliseconds * Global.tileSize.Y*jumpPower)))
            {
                if (isJump && Speed.Y > 0)
                {
                        isJump = false;
                    jumpKeyReleased = false;
                }
                if (Speed.Y > 0.03f)
                    isDuck = true;
                Speed.Y = 0;
            }
            if (isCollide(new Vector2(Location.X + Speed.X * gameTime.ElapsedGameTime.Milliseconds * Global.tileSize.X*movementSpeed, Location.Y + Speed.Y * gameTime.ElapsedGameTime.Milliseconds * Global.tileSize.Y*jumpPower)))
            {
                if (isJump && Speed.Y > 0)
                {
                    isJump = false;
                    jumpKeyReleased = false;
                } 
                if (Speed.Y > 0.03f)
                    isDuck = true;
                Speed.X = 0;
                Speed.Y = 0;
            }
            Location.X = (Location.X + Speed.X*gameTime.ElapsedGameTime.Milliseconds*Global.tileSize.X*movementSpeed + Global.currentWorld.tiles.MapWidth * Global.tileSize.X) % 
                (Global.currentWorld.tiles.MapWidth * Global.tileSize.X);
            Location.Y = (Location.Y + Speed.Y*gameTime.ElapsedGameTime.Milliseconds*Global.tileSize.Y*jumpPower + Global.currentWorld.tiles.MapHeight * Global.tileSize.Y) % 
                (Global.currentWorld.tiles.MapHeight * Global.tileSize.Y);
            if (Math.Abs(Speed.X) < 0.0001f)
                Speed.X = 0;
            if (Math.Abs(Speed.Y) < 0.0001f)
                Speed.Y = 0;
        }
        bool isCollide(Vector2 Location)
        {
            Rectangle player = new Rectangle((int)Location.X + 15, (int)Location.Y + 20, 30, 40);
            for (int i = (int)Math.Floor((float)(Location.X - 15) / Global.tileSize.X); i <  (int)Math.Ceiling((float)(Location.X + 15) / Global.tileSize.X); i++)
            {
                for (int j = (int)Math.Floor((float)(Location.Y - 20) / Global.tileSize.Y); j < (int)Math.Ceiling((float)(Location.Y + 20) / Global.tileSize.Y); j++)
                    if (parentWorld.tiles[i,j].tile.GetType() != typeof(Empty))
                        if(parentWorld.tiles[i,j].tile.isObstacle())
                            return true;
            }
            return false;
        }

        public void addXp(int x)
        {
            xp+=x;
            totalXp += x;
            if (xp > nextXP)
            {
                xp = 0;
                level++;
                nextXP= nextXP*1.1;
                stat += 5;
            }
        }

        #region drawing
        public void draw(SpriteBatch spriteBatch, GameTime gameTime,Color tint)
        {
            if (isJump)
            {
                if (Speed.Y < 0)
                    drawJump(spriteBatch, gameTime, tint);
                else
                    drawFall(spriteBatch, gameTime, tint);
            }
            else if (Speed.Y > 0.01f)
                drawFall(spriteBatch, gameTime, tint);
            else
            {
                if (isDuck)
                    drawDuck(spriteBatch, gameTime, tint);
                else if (isLieDown)
                    drawLieDown(spriteBatch, gameTime, tint);
                else if (isStandingup)
                    drawStandingUp(spriteBatch, gameTime, tint);
                else if (Math.Abs(Speed.X) < 0.003f)
                    drawStand(spriteBatch, gameTime, tint);
                else
                {
                    drawRun(spriteBatch, gameTime, tint);
                }
            }
            if (isFiring && !isDuck && !isLieDown && !isStandingup)
            {
                if (inventory.holders[inventory.selected].items.Count != 0)
                    inventory.holders[inventory.selected].items[0].useDraw(spriteBatch, tint);
            }
            if (!inventory.isShown)
                status.draw(spriteBatch);
        }
        void drawLieDown(SpriteBatch spriteBatch, GameTime gameTime, Color tint)
        {
            if (DuckTime < 150)
                DuckTime += gameTime.ElapsedGameTime.Milliseconds;
            else
            {
                DuckTime = 150;
            }
            spriteBatch.Draw(Textures.player, Location - Camera.Location, new Rectangle((DuckTime / 50) * 50, 200, 50, 50), tint, 0f, new Vector2(25, 25), 1f, isLookRight ? SpriteEffects.None : SpriteEffects.FlipHorizontally, 0f);
        }
        void drawDuck(SpriteBatch spriteBatch, GameTime gameTime, Color tint)
        {
            DuckTime += gameTime.ElapsedGameTime.Milliseconds;
            if (DuckTime > 300)
            {
                DuckTime = 0;
                isDuck = false;
            }
            spriteBatch.Draw(Textures.player, Location - Camera.Location, new Rectangle((DuckTime / 50) * 50, 150, 50, 50), tint, 0f, new Vector2(25, 25), 1f, isLookRight ? SpriteEffects.None : SpriteEffects.FlipHorizontally, 0f);
        }
        void drawStandingUp(SpriteBatch spriteBatch, GameTime gameTime, Color tint)
        {
            DuckTime += gameTime.ElapsedGameTime.Milliseconds;
            if (DuckTime >= 400)
            {
                DuckTime = 0;
                isStandingup = false;
                return;
            }
            spriteBatch.Draw(Textures.player, Location - Camera.Location, new Rectangle((DuckTime / 50) * 50, 250, 50, 50), tint, 0f, new Vector2(25, 25), 1f, isLookRight ? SpriteEffects.None : SpriteEffects.FlipHorizontally, 0f);
        }
        void drawJump(SpriteBatch spriteBatch, GameTime gameTime, Color tint)
        {
            spriteBatch.Draw(Textures.player, Location - Camera.Location, new Rectangle(isFiring ? 50 : 0, 50, 50, 50), tint, 0f, new Vector2(25, 25), 1f, isLookRight ? SpriteEffects.None : SpriteEffects.FlipHorizontally, 0f);
        }
        void drawFall(SpriteBatch spriteBatch, GameTime gameTime, Color tint)
        {
            int frame = (int)(((Location.Y % (Global.tileSize.Y * 4)) * 3) / (Global.tileSize.Y * 4));
            spriteBatch.Draw(Textures.player, Location - Camera.Location, new Rectangle(frame * 50 + (isFiring ? 150 : 0), 100, 50, 50), tint, 0f, new Vector2(25, 25), 1f, isLookRight ? SpriteEffects.None : SpriteEffects.FlipHorizontally, 0f);
        }
        void drawRun(SpriteBatch spriteBatch, GameTime gameTime, Color tint)
        {
            int frame = (int)(((Location.X % (Global.tileSize.X * 4)) * 6) / (Global.tileSize.X * 4));
            spriteBatch.Draw(Textures.player, Location - Camera.Location, new Rectangle(frame * 50, 300 + (isFiring ? 50 : 0), 50, 50), tint, 0f, new Vector2(25, 25), 1f, isLookRight ? SpriteEffects.None : SpriteEffects.FlipHorizontally, 0f);
        }
        void drawStand(SpriteBatch spriteBatch, GameTime gameTime, Color tint)
        {
            spriteBatch.Draw(Textures.player, Location - Camera.Location, new Rectangle(isFiring ? 50 : 0, 0, 50, 50), tint, 0f, new Vector2(25, 25), 1f, isLookRight ? SpriteEffects.None : SpriteEffects.FlipHorizontally, 0f);
        }
        #endregion

        public bool load()
        {
            return true;
        }
        public bool save()
        {
            List<string> file = new List<string>();
            for (int i = 0; i < inventory.holders.Count; i++)
            {
                if (inventory.holders[i].items.Count != 0)
                    file.Add(ItemIndexer.items.IndexOf(inventory.holders[i].items[0].GetType()).ToString());
                 else
                    file.Add("-1");
                file.Add(inventory.holders[i].items.Count.ToString());
            }
            
            //inventory
            //spawnTile
            //full stats
            //achievements
            return true;
        }

    }
}
